define(['underscore', "tween", "three", "OrbitControls", "GLTFLoader"], (_, TWEEN, THREE) ->
  class Scene
    constructor: (dom) -> (
      @height = dom.clientHeight
      @width = dom.clientWidth
      
      @initCamera()
      @initScene()
      @initLight()
      @initRender()
      
      dom.appendChild(@renderer.domElement)

      @loadModel()
      
      @render()
    )

    initCamera: () -> (
      @camera = new THREE.PerspectiveCamera(45, @width / @height, 1, 5000);
      @camera.position.set(0.258, 4.288, 10.322);
      @camera.lookAt(0, 0, 0)
      @controls = new THREE.OrbitControls(@camera);
      @controls.rotateSpeed = 1.0;
      @controls.zoomSpeed = 1.2;
      @controls.panSpeed = 0.8;
    )

    initScene: () -> (
      @scene = new THREE.Scene()
      @scene.background = new THREE.Color("rgb(200, 200, 200)")
      console.log(@scene)
    )

    initLight: () -> (
      @light = new THREE.HemisphereLight(0xffbf67, 0x15c6ff)
      @scene.add(@light)
    )

    initRender: () -> (
      @renderer = new THREE.WebGLRenderer({ antialias: true, precision: "highp", alpha: true  })
      @renderer.setSize(@width, @height);
      @renderer.setClearColor(0x000000, 0)
      @renderer.gammaOutput = true
    )

    loadModel: () -> (
      gltfLoader = new THREE.GLTFLoader()
      gltfLoader.load("static/asset/3d/scene.gltf", (gltf) => (
        @scene.add(gltf.scene.children[0], gltf.scene.children[1], gltf.scene.children[2], gltf.scene.children[3])
      ))
    )

    render: () -> (
      TWEEN.update();
      window.requestAnimationFrame(@render.bind(@))
      @renderer.render(@scene, @camera);
      @controls.update()
    )

    changeCamera: (index) -> (
      from = [0, 0]
      to = [-Math.PI * 3 / 4, Math.PI * 3 / 4]
      
      @tween = new TWEEN.Tween(from)
        .to(to, 4000)
        .easing(TWEEN.Easing.Linear.None)
        .onUpdate(() =>
          @scene.children[1].rotation.set(0, from[0], 0)
          @scene.children[2].rotation.set(0, from[1], 0)
        )
        .onComplete(() => 
          @scene.children[1].rotation.set(0, to[0], 0)
          @scene.children[2].rotation.set(0, to[1], 0)
        )
        .start();
    )

    changeBtn: () => (
      if @tween
        @tween.stop()
        TWEEN.remove(@tween)
      @list = [
        @target, 
        { x: 382, y: 221, z: -307 },
        { x: 2, y: -578, z: -212 },
        { x: -371, y: 221, z: -320 },
        { x: 0, y: 601, z: -136 },
        @target
      ]
      @changeCamera(0)
    )

  return Scene
)